/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.colswe.testingProject.dao;

import java.util.Collection;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import org.colswe.testingProject.entity.Student;

/**
 * La clase StudentDao encargada de operaciones CRU para los estudiantes en la
 * base de datos.
 *
 * @author andres
 */
public class StudentDao {

    /**
     * EntityManagerGactory necesario para crear EntityManager para las
     * operaciones en la base de datos.
     */
    private EntityManagerFactory emf;

    /**
     * Constructor de la clase StudentDao.
     *
     * @param emf EntityManagerFactory necesario para la comunicación con la
     * base de datos
     */
    public StudentDao(EntityManagerFactory emf) {
        this.emf = emf;
    }

    /**
     * Función que permite la persistencia de un objeto en la base de datos.
     *
     * @param toCreate Objeto Student que se va a persistir
     * @return Verdadero si la operación fue correcta, falso en caso contrario
     */
    public boolean create(Student toCreate) {
        boolean result = true;
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(toCreate);
            em.getTransaction().commit();
        } catch (Exception ex) {
            result = false;
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
        } finally {
            if (em != null) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Función que permite la actualización de un objeto en la base de datos.
     *
     * @param toUpdate Objeto Student que se va a actualizar
     * @return Verdadero si la operación fue correcta, falso en caso contrario
     */
    public boolean update(Student toUpdate) {
        boolean result = true;
        EntityManager em = emf.createEntityManager();
        Student old;
        try {
            old = read(toUpdate);
            if (old != null) {
                toUpdate.setId(old.getId());
                em.getTransaction().begin();
                em.merge(toUpdate);
                em.getTransaction().commit();
            } else {
                throw new Exception("The registry does not exist");
            }
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            if (em.isOpen()) {
                em.getTransaction().rollback();
            }
            result = false;
        } finally {
            if (em != null && em.isOpen()) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Función que permite la lectura de un objeto en la base de datos.
     *
     * @param toRead Objeto Student que se va a leer de la base de datos
     * @return Una instancia de Student, si existe en la base de datos, null en
     * caso contrario
     */
    public Student read(Student toRead) {
        EntityManager em = emf.createEntityManager();
        Student student;
        try {
            Query query = em.createQuery("SELECT u FROM Student AS u "
                    + "WHERE u.idNumber= :idParam");
            query.setParameter("idParam", toRead.getIdNumber());
            em.getTransaction().begin();
            student = (Student) query.getSingleResult();
            em.getTransaction().commit();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            student = null;
        } finally {
            if (em != null && em.isOpen()) {
                em.close();
            }
        }
        return student;
    }

    /**
     * Función que permite la lectura de todos los objetos Student.
     *
     * @return Colección con todos los Student, null si se presenta algún
     * problema
     */
    public Collection<Student> readAll() {
        Collection<Student> result;
        EntityManager em = emf.createEntityManager();
        try {
            Query query = em.createQuery("SELECT u FROM Student AS u");
            em.getTransaction().begin();
            result = query.getResultList();
            em.getTransaction().commit();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            result = null;
        } finally {
            if (em != null && em.isOpen()) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Método que elimina objetos de tipo {@link Student}.
     *
     * @param toDelete El objeto a eliminar
     * @return True si la eliminación fue exitosa. False si hubieron errores
     */
    public boolean delete(Student toDelete) {
        boolean result = true;
        EntityManager em = emf.createEntityManager();
        try {
            toDelete = read(toDelete);
            if (toDelete != null) {
                em.getTransaction().begin();
                toDelete = em.getReference(Student.class, toDelete.getId());
                em.remove(toDelete);
                em.getTransaction().commit();
            } else {
                throw new Exception("The registry does not exist");
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace(System.err);
            result = false;
        } finally {
            if (em != null) {
                em.close();
            }
        }
        return result;
    }
}
